package packet

import (
	"fmt"
	"github.com/google/gopacket"
	"github.com/google/gopacket/layers"
	"github.com/google/gopacket/pcap"
	"net"
)

type OSPFParser struct {
	handle *pcap.Handle
}

// NewOSPFParser 创建一个ospf类型解析器
func NewOSPFParser(pcapFile string) (*OSPFParser, error) {
	handle, err := pcap.OpenOffline(pcapFile)
	if err != nil {
		return nil, err
	}

	return &OSPFParser{handle: handle}, nil
}

func (p *OSPFParser) Start() chan *OSPFPacket {
	//创建一个容量为1000的channel通道
	out := make(chan *OSPFPacket, 1000)

	go func() {
		defer close(out)
		defer p.handle.Close()

		for {
			pkt, err := p.ParsePacket()
			if err != nil {
				fmt.Println(err)
				break
			}
			if pkt != nil {
				out <- pkt
			}
		}
	}()

	return out
}

func (p *OSPFParser) ParsePacket() (*OSPFPacket, error) {
	data, _, err := p.handle.ReadPacketData()
	if err != nil {
		return nil, err
	}

	packet := gopacket.NewPacket(data, layers.LayerTypeEthernet, gopacket.Default)

	// 检查IP层
	ipLayer := packet.Layer(layers.LayerTypeIPv4)
	if ipLayer == nil {
		return nil, nil
	}
	ip, _ := ipLayer.(*layers.IPv4)

	// 检查OSPF层
	ospfLayer := packet.Layer(layers.LayerTypeOSPF)
	if ospfLayer == nil {
		return nil, nil
	}

	ospf, _ := ospfLayer.(*layers.OSPFv2)

	// 创建基础OSPFPacket
	ospfPkt := &OSPFPacket{
		Timestamp:    packet.Metadata().Timestamp,
		SourceIP:     ip.SrcIP,
		DestIP:       ip.DstIP,
		Version:      ospf.Version,
		Type:         ospf.Type,
		PacketLength: ospf.PacketLength,
		RouterID:     Uint32ToIP(ospf.RouterID),
		AreaID:       Uint32ToIP(ospf.AreaID),
		Checksum:     ospf.Checksum,
		AuType:       ospf.AuType,
	}

	// 根据包类型解析具体内容
	switch ospf.Type {
	case layers.OSPFHello:
		if err := p.parseHelloPacket(ospf.Content, ospfPkt); err != nil {
			return nil, err
		}
	case layers.OSPFDatabaseDescription:
		if err := p.parseDDPacket(ospf.Content, ospfPkt); err != nil {
			return nil, err
		}
	case layers.OSPFLinkStateRequest:
		if err := p.parseLSRPacket(ospf.Content, ospfPkt); err != nil {
			return nil, err
		}
	case layers.OSPFLinkStateUpdate:
		if err := p.parseLSRPacket(ospf.Content, ospfPkt); err != nil {
			return nil, err
		}
	case layers.OSPFLinkStateAcknowledgment:
		if err := p.parseLSAckPacket(ospf.Content, ospfPkt); err != nil {
			return nil, err
		}
	default:
		fmt.Println("this OSPF packet is not supported!")
	}

	return ospfPkt, nil
}

func (p *OSPFParser) parseHelloPacket(content interface{}, ospfPkt *OSPFPacket) error {
	// 首先尝试HelloPkgV2类型
	if hello, ok := content.(layers.HelloPkgV2); ok {
		ospfPkt.HelloFields = &HelloFields{
			NetworkMask:            net.IPMask(Uint32ToIP(hello.NetworkMask)),
			HelloInterval:          hello.HelloInterval,
			Options:                hello.Options,
			Priority:               hello.RtrPriority,
			DeadInterval:           hello.RouterDeadInterval,
			DesignatedRouter:       Uint32ToIP(hello.DesignatedRouterID),
			BackupDesignatedRouter: Uint32ToIP(hello.BackupDesignatedRouterID),
			Neighbors:              make([]net.IP, len(hello.NeighborID)),
		}

		// 转换邻居IP
		for i, neighbor := range hello.NeighborID {
			ospfPkt.HelloFields.Neighbors[i] = Uint32ToIP(neighbor)
		}
		return nil
	}

	// 然后尝试HelloPkg类型
	if hello, ok := content.(layers.HelloPkg); ok {
		ospfPkt.HelloFields = &HelloFields{
			NetworkMask:            net.IPMask(Uint32ToIP(0)), //HelloPkg没有NetworkMask
			HelloInterval:          hello.HelloInterval,
			Options:                hello.Options,
			Priority:               hello.RtrPriority,
			DeadInterval:           hello.RouterDeadInterval,
			DesignatedRouter:       Uint32ToIP(hello.DesignatedRouterID),
			BackupDesignatedRouter: Uint32ToIP(hello.BackupDesignatedRouterID),
			Neighbors:              make([]net.IP, len(hello.NeighborID)),
		}

		// 转换邻居IP
		for i, neighbor := range hello.NeighborID {
			ospfPkt.HelloFields.Neighbors[i] = Uint32ToIP(neighbor)
		}
		return nil
	}

	return fmt.Errorf("invalid Hello packet content: neither HelloPkgV2 nor HelloPkg")
}

// parseDDPacket 解析DD包内容
func (p *OSPFParser) parseDDPacket(content interface{}, ospfPkt *OSPFPacket) error {
	dd, ok := content.(*layers.DbDescPkg)
	if !ok {
		return fmt.Errorf("invalid DD packet content")
	}

	ospfPkt.DDFields = &DDFields{
		InterfaceMTU: dd.InterfaceMTU,
		Options:      dd.Options,
		Flags:        dd.Flags,
		DDSequence:   dd.DDSeqNumber,
		LSAHeaders:   make([]LSAHeader, len(dd.LSAinfo)),
	}

	// 转换LSA Headers
	for i, lsa := range dd.LSAinfo {
		ospfPkt.DDFields.LSAHeaders[i] = LSAHeader{
			Age:               lsa.LSAge,
			Options:           lsa.LSOptions,
			Type:              lsa.LSType,
			LSID:              Uint32ToIP(lsa.LinkStateID),
			AdvertisingRouter: Uint32ToIP(lsa.AdvRouter),
			SequenceNum:       lsa.LSSeqNumber,
			Checksum:          lsa.LSChecksum,
			Length:            lsa.Length,
		}
	}

	return nil
}

// 添加LSR包解析函数
func (p *OSPFParser) parseLSRPacket(content interface{}, ospfPkt *OSPFPacket) error {
	// 尝试类型断言
	lsr, ok := content.(*layers.LSReq)
	if !ok {
		return fmt.Errorf("invalid LSR packet content: unknown type %T", content)
	}

	ospfPkt.LSRFields = &LSRFields{
		LSARequests: []LSARequest{
			{
				LSType:            lsr.LSType,
				LSID:              Uint32ToIP(lsr.LSID),
				AdvertisingRouter: Uint32ToIP(lsr.AdvRouter),
			},
		},
	}

	return nil
}

func (p *OSPFParser) parseLSUPacket(content interface{}, ospfPkt *OSPFPacket) error {
	lsu, ok := content.(*layers.LSUpdate)
	if !ok {
		return fmt.Errorf("invalid LSU packet content: unknown type %T", content)
	}

	ospfPkt.LSUFields = &LSUFields{
		NumOfLSAs: lsu.NumOfLSAs,
		LSAs:      make([]LSAFields, 0, lsu.NumOfLSAs),
	}

	// 解析LSAs
	for _, lsa := range lsu.LSAs {
		newLSA := LSAFields{
			Header: LSAHeader{
				Age:               lsa.LSAheader.LSAge,
				Options:           lsa.LSAheader.LSOptions,
				Type:              lsa.LSAheader.LSType,
				LSID:              Uint32ToIP(lsa.LSAheader.LinkStateID),
				AdvertisingRouter: Uint32ToIP(lsa.LSAheader.AdvRouter),
				SequenceNum:       lsa.LSAheader.LSSeqNumber,
				Checksum:          lsa.LSAheader.LSChecksum,
				Length:            lsa.LSAheader.Length,
			},
			Content: lsa.Content,
		}
		ospfPkt.LSUFields.LSAs = append(ospfPkt.LSUFields.LSAs, newLSA)
	}

	return nil
}

// 添加LSAck包解析函数
func (p *OSPFParser) parseLSAckPacket(content interface{}, ospfPkt *OSPFPacket) error {
	// 类型断言为[]LSAheader
	lsaHeaders, ok := content.([]layers.LSAheader)
	if !ok {
		return fmt.Errorf("invalid LSAck packet content: unknown type %T", content)
	}

	ospfPkt.LSAckFields = &LSAckFields{
		LSAHeaders: make([]LSAHeader, len(lsaHeaders)),
	}

	// 解析每个LSA header
	for i, header := range lsaHeaders {
		ospfPkt.LSAckFields.LSAHeaders[i] = LSAHeader{
			Age:               header.LSAge,
			Options:           header.LSOptions,
			Type:              header.LSType,
			LSID:              Uint32ToIP(header.LinkStateID),
			AdvertisingRouter: Uint32ToIP(header.AdvRouter),
			SequenceNum:       header.LSSeqNumber,
			Checksum:          header.LSChecksum,
			Length:            header.Length,
		}
	}

	return nil
}
